package com.hxl.tech.gateway.auth.service;

import com.alibaba.fastjson.JSONObject;
import com.hxl.tech.gateway.auth.context.ContextHolder;
import com.hxl.tech.gateway.auth.dao.LimitRuleDao;
import com.hxl.tech.gateway.auth.dto.Page;
import com.hxl.tech.gateway.auth.dto.UserInfo;
import com.hxl.tech.gateway.auth.dto.limitrule.LimitRuleFindDTO;
import com.hxl.tech.gateway.auth.exception.AuthException;
import com.hxl.tech.gateway.auth.model.LimitRule;
import com.hxl.tech.gateway.auth.util.AutoGenerateIDUtil;
import com.hxl.tech.gateway.common.constant.AppConstant;
import com.hxl.tech.gateway.common.constant.Result;
import com.hxl.tech.gateway.common.util.RedisUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 限流配置 Service 
 * @author soliddq
 * @date 2023-10-16
 */
@Service
@RequiredArgsConstructor
@Transactional
public class LimitRuleService {

    private final LimitRuleDao limitRuleDao;
    private final EntityManager entityManager;

    public Page<LimitRule> page(LimitRuleFindDTO findDTO) {

        List<LimitRule> list = limitRuleDao.find(findDTO, true);
        Long total = limitRuleDao.count(findDTO);
        return Page.of(findDTO, total, list);
    }

    public List<LimitRule> findAll() {

        return limitRuleDao.findAll();
    }

    public LimitRule read(String ruleId) {

        return limitRuleDao.read(ruleId);
    }


    public LimitRule save(LimitRule limitRule) {

        UserInfo userInfo = ContextHolder.getUserInfo();
        limitRule.setRuleId(AutoGenerateIDUtil.next(AppConstant.PREFIX_RULE));
        limitRule.setCreateBy(userInfo.getRealName());
        limitRule.setCreateTime(LocalDateTime.now());
        limitRule.setUpdateBy(limitRule.getCreateBy());
        limitRule.setUpdateTime(limitRule.getCreateTime());
        entityManager.persist(limitRule);

        String key = limitRule.getRuleId() + "_" + limitRule.getAppId() + "_" +limitRule.getMerchantCode() + "_"  + limitRule.getApiName();
        RedisUtil.set(AppConstant.REDIS_LIMIT_RATE_RULE+key, JSONObject.toJSONString(limitRule), 0 , TimeUnit.DAYS);
        return limitRule;
    }

    public LimitRule update(LimitRule limitRule) {

        LimitRule origLimitRule = this.read(limitRule.getRuleId());
        if (Objects.isNull(origLimitRule)) {
            throw new AuthException(Result.E10007);
        }

        UserInfo userInfo = ContextHolder.getUserInfo();
        if (StringUtils.isNotBlank(limitRule.getRuleName())) {
            origLimitRule.setRuleName(limitRule.getRuleName());
        }
        if (StringUtils.isNotBlank(limitRule.getRuleDesc())) {
            origLimitRule.setRuleDesc(limitRule.getRuleDesc());
        }
        origLimitRule.setAppId(limitRule.getAppId());
        origLimitRule.setMerchantCode(limitRule.getMerchantCode());
        origLimitRule.setApiName(limitRule.getApiName());
        origLimitRule.setLimitCount(limitRule.getLimitCount());
        origLimitRule.setLimitTimeUnit(limitRule.getLimitTimeUnit());
        origLimitRule.setUpdateBy(userInfo.getRealName());
        origLimitRule.setUpdateTime(LocalDateTime.now());
        entityManager.merge(origLimitRule);

        String key = origLimitRule.getRuleId() + "_" + origLimitRule.getAppId() + "_" +origLimitRule.getMerchantCode() + "_"  + origLimitRule.getApiName();
        RedisUtil.set(AppConstant.REDIS_LIMIT_RATE_RULE + key,  JSONObject.toJSONString(origLimitRule), 0 , TimeUnit.DAYS);
        return origLimitRule;

    }

    public void delete(String ruleId) {

        LimitRule origLimitRule = this.read(ruleId);
        if (Objects.nonNull(origLimitRule)) {
            entityManager.remove(origLimitRule);
            String key = ruleId + "_" + origLimitRule.getAppId() + "_" +origLimitRule.getMerchantCode() + "_"  + origLimitRule.getApiName();
            RedisUtil.delete(AppConstant.REDIS_LIMIT_RATE_RULE+key);
        }
    }
}
